# -*- coding: utf8 -*-
#
# Copyright (c) 2009 Matías Ribecky <status-notifications@mribecky.com.ar>
#
# This file is part of status-notifications.
# 
# status-notifications is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# status-notifications is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with status-notifications.  If not, see <http://www.gnu.org/licenses/>.

import socket
import logging
import imaplib
import datetime
import email.utils
import email.parser

from pluginlib.plugin import Implementation

import statusnotifications.data
from statusnotifications.status import Status
from statusnotifications.config import Account

__all__ = ['GmailNetworkError', 'GmailServiceError', 'GmailStatusProvider']

GMAIL_ICON = 'file://' + statusnotifications.data.get('gmail_logo.png')
LOGGER = logging.getLogger('statusnotifications.gmail')

def load(ctx):
    ctx.add_implementation(GmailStatusProvider)
    ctx.add_implementation(GmailNetworkError)
    ctx.add_implementation(GmailServiceError)

class GmailNetworkError(Implementation, Exception):

    iface_name = 'NetworkError'
    display_name = "Gmail network error"

    def __init__(self, *args, **kwargs):
        Implementation.__init__(self)
        Exception.__init__(self, *args, **kwargs)

class GmailServiceError(Implementation, Exception):
    """An error in the communications to the server."""

    iface_name = 'StatusProviderError'
    display_name = "Gmail service error"

    def __init__(self, *args, **kwargs):
        Implementation.__init__(self)
        Exception.__init__(self, *args, **kwargs)

class GmailStatusProvider(Implementation):

    iface_name = 'StatusProvider'
    display_name = "Gmail mail"

    image_name = 'gmail_logo.png'

    def __init__(self, username, password):
        self.displayed_mail = set()
        self._login(username, password)

    def _login(self, username, password):
        try:
            LOGGER.info('Connecting to Gmail server')
            self.con = imaplib.IMAP4_SSL('imap.gmail.com', 993)
            LOGGER.info('Logging in to account %s' % username)
            try:
                resp = self.con.login(username, password)
                if resp[0] != 'OK':
                    raise GmailServiceError("Could not login with username %s",
                                            username)
            except imaplib.IMAP4_SSL.error, e:
                raise GmailServiceError(str(e))

            LOGGER.debug('Logging in successful')

            resp = self.con.select('inbox')
            if resp[0] != 'OK':
                raise GmailServiceError()
        except socket.error, e:
            raise GmailNetworkError(e.strerror)

    def close(self):
        self.con.close()
        self.con.logout()

    def get_new_statuses(self):
        '''Get a list of the new mail.'''

        LOGGER.info("Checking for new mail")
        rsp = self.con.search(None, 'UNSEEN')
        LOGGER.debug("New messages: %s" % rsp[1][0])
        LOGGER.debug("Displayed messages: %s" % ' '.join(self.displayed_mail))
        not_shown = [msg_no for msg_no in rsp[1][0].split()
                                if msg_no not in self.displayed_mail]
        self.displayed_mail.update(not_shown)
        LOGGER.debug("New not displayed messages: %s" % ' '.join(not_shown))

        for new_message in not_shown:
            self.displayed_mail.add(new_message)
            resp = self.con.fetch(new_message, '(RFC822)')
            parser = email.parser.FeedParser()
            parser.feed(resp[1][0][1])
            msg = parser.close()

            name, screen_name = email.utils.parseaddr(msg['From'])
            date = email.utils.parsedate(msg['Date'])
            date = datetime.datetime(*date[:6])
            status = {'id': new_message,
                      'user': {'name': name,
                               'screen_name': screen_name,
                               'created_at': None,
                               'profile_image_url': GMAIL_ICON,
                               'description': u'',
                               'url': u'mailto:%s' % screen_name},
                      'text': msg['Subject'],
                      'created_at': date,
                      'service_name': 'GMail'}
            yield Status(status)

    @classmethod
    def load_create_form(cls, form):
        user_data = {'username': u'',
                     'password': u''}

        form.text_value(u"Username:", user_data, 'username')
        form.text_value(u"Password:", user_data, 'password', is_password=True)

        form.show_all()

        return user_data

    @classmethod
    def create_account(cls, user_data):
        account = Account('Gmail-' + user_data['username'],
                          cls,
                          user_data['username'])
        account.password = user_data['password']
        return account


